package com.qqtech.qquan.circle.service;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.qqtech.core.common.enums.YesNoEnum;
import com.qqtech.core.common.exception.BizzException;
import com.qqtech.core.common.util.TimeUtil;
import com.qqtech.core.frame.dao.BaseDao;
import com.qqtech.core.frame.model.PageKit;
import com.qqtech.core.frame.model.PageOrder;
import com.qqtech.core.frame.service.BaseServiceImpl;
import com.qqtech.qquan.circle.dao.CircleBaseDao;
import com.qqtech.qquan.circle.dao.CircleInfoDao;
import com.qqtech.qquan.circle.dao.CircleMemberDao;
import com.qqtech.qquan.circle.enums.CircleAuditStatusEnum;
import com.qqtech.qquan.circle.enums.CircleBaseStatusDictEnum;
import com.qqtech.qquan.circle.enums.CircleBaseTypeDictEnum;
import com.qqtech.qquan.circle.enums.CircleFuncTypeDictEnum;
import com.qqtech.qquan.circle.enums.CircleMemberTypeDictEnum;
import com.qqtech.qquan.circle.enums.CircleOpenLevelDictEnum;
import com.qqtech.qquan.circle.model.CircleBase;
import com.qqtech.qquan.circle.model.CircleBaseQuery;
import com.qqtech.qquan.circle.model.CircleBaseVo;
import com.qqtech.qquan.circle.model.CircleInfo;
import com.qqtech.qquan.circle.model.CircleMember;
import com.qqtech.qquan.circle.model.CircleMemberQuery;
import com.qqtech.qquan.community.dao.CommunityBaseDao;
import com.qqtech.qquan.community.model.CommunityBase;
import com.qqtech.qquan.im.service.ImGroupService;

@Service
public class CircleBaseServiceImpl extends BaseServiceImpl<CircleBase> implements CircleBaseService {
	public static final Logger log = LoggerFactory.getLogger(CircleBaseServiceImpl.class);

	@Resource
	private CircleBaseDao circleBaseDao;
	@Resource
	private CircleMemberDao circleMemberDao;
	@Resource
	private CircleInfoDao circleInfoDao;
	@Resource
	private CircleSysDictService circleSysDictService;
	@Resource
	private CommunityBaseDao communityBaseDao;

	@Resource
	private ImGroupService imGroupService;

	@Override
	protected BaseDao<CircleBase> getBaseDao() {
		return circleBaseDao;
	}

	@Override
	public int addCircle(CircleBase circleBase) throws BizzException {
		boolean canChat = false;// 是否可以群聊
		checkCircleName(circleBase);
		circleBase.setStatus(CircleBaseStatusDictEnum.NORMAL.getCode());
		if (circleBase.getCategoryName() == null) {
			circleBase.setCategoryName("");
		}
		Integer circleType = circleBase.getType();// 圈子类型：1-官方;2-民间

		if (circleType == CircleBaseTypeDictEnum.OFFICIAL.getCode()) {
			// 官方圈子--只能发话题
			circleBase.setFuncType(CircleFuncTypeDictEnum.TOPICONLY.getCode());
			canChat = false;
		} else if (circleType == CircleBaseTypeDictEnum.POPULAR.getCode()) {
			// 民间圈子--可以发话题及聊天
			circleBase.setFuncType(CircleFuncTypeDictEnum.ALL.getCode());//
			canChat = true;
		}
		if (circleBase.getOpenLevel() == null) {
			circleBase.setOpenLevel(CircleOpenLevelDictEnum.FULL_OPEN.getCode());// 如果不设置,默认完全公开（用户可以自由加入）
		}
		int circleId = this.insert(circleBase);// 1.保存圈子主表信息
		CircleMember circleMember = new CircleMember();
		circleMember.setCircleId(circleId);
		circleMember.setMemberId(circleBase.getCreatorId());
		circleMember.setType(CircleMemberTypeDictEnum.OWNER.getCode());
		circleMemberDao.insert(circleMember);// 2.保存圈子成员【圈主】

		CircleInfo circleInfo = new CircleInfo();
		circleInfo.setId(circleId);
		circleInfo.setMemberCount(1);
		circleInfo.setTopicCount(0);
		circleInfo.setPv(0);
		circleInfoDao.insert(circleInfo);// 3.保存圈子扩展信息
		if (canChat) {
			imGroupService.addImGroup(circleId, circleBase.getName(), 1000, circleBase.getCreatorId());// 添加IM群组
		}
		return circleId;
	}

	@Override
	public Page<CircleBaseVo> queryPageListAdmin(CircleBaseQuery query, Pageable pageable) {
		return circleBaseDao.queryPageListAdmin(query, pageable);
	}

	@Override
	public boolean isCircleCreator(Integer userId, Integer circleId) {
		CircleBase circle = new CircleBase();
		circle.setCreatorId(userId);
		circle.setId(circleId);
		circle.setStatus(CircleBaseStatusDictEnum.NORMAL.getCode());
		return circleBaseDao.queryCount(circle) > 0;
	}

	@Override
	public List<CircleBaseVo> queryMyCircles(CircleMemberQuery query) {
		List<Integer> myCircleIds = circleMemberDao.queryMyCircleIds(query);
		if (myCircleIds != null && myCircleIds.size() > 0) {
			return this.queryListByCircleIds(myCircleIds);
		} else {
			return Lists.newArrayList();
		}
	}

	@Override
	public List<CircleBaseVo> queryMyOrderlyCircles(int userId) {
		return circleBaseDao.queryMyOrderlyCircles(userId);
	}

	@Override
	public List<CircleBaseVo> queryMyOpenCircles(int userId) {
		List<Integer> myCircleIds = circleMemberDao.queryMyOpenCircleIds(userId);
		if (myCircleIds != null && myCircleIds.size() > 0) {
			return this.queryListByCircleIds(myCircleIds);
		} else {
			return Lists.newArrayList();
		}
	}

	@Override
	public List<CircleBaseVo> queryMyCreatedCircles(int userId) {
		List<Integer> myCircleIds = circleMemberDao.queryMyCreatedCircleIds(userId);
		if (myCircleIds != null && myCircleIds.size() > 0) {
			return this.queryListByCircleIds(myCircleIds);
		} else {
			return Lists.newArrayList();
		}
	}

	@Override
	public List<CircleBaseVo> queryMyJoinCircles(int userId) {
		List<Integer> myCircleIds = circleMemberDao.queryMyJoinCircleIds(userId);
		if (myCircleIds != null && myCircleIds.size() > 0) {
			return this.queryListByCircleIds(myCircleIds);
		} else {
			return Lists.newArrayList();
		}
	}

	@Override
	public void deleteCircle(Integer circleId) {
		CircleBase circle = new CircleBase();
		circle.setId(circleId);
		circle.setStatus(CircleBaseStatusDictEnum.DELETE.getCode());// 2删除状态
		int updateRow = circleBaseDao.updateById(circle);
		if (updateRow == 1) {
			CircleInfo circleInfo = new CircleInfo();
			circleInfo.setId(circleId);
			circleInfo.setMemberCount(0);
			circleInfoDao.updateById(circleInfo);// 圈子成员数量-设置为0

			CircleMember circleMember = new CircleMember();
			circleMember.setCircleId(circleId);
			circleMemberDao.delete(circleMember);// 删除全体圈子成员
			imGroupService.deleteGroup(circleId);// 删除IM群组
		}

	}

	@Override
	public void dismissCircle(Integer circleId) {
		CircleBase circle = new CircleBase();
		circle.setId(circleId);
		circle.setStatus(CircleBaseStatusDictEnum.DISMISS.getCode());// 3解散状态
		int updateRow = circleBaseDao.updateById(circle);
		if (updateRow == 1) {
			CircleInfo circleInfo = new CircleInfo();
			circleInfo.setId(circleId);
			circleInfo.setMemberCount(0);
			circleInfoDao.updateById(circleInfo);// 圈子成员数量-设置为0

			CircleMember circleMember = new CircleMember();
			circleMember.setCircleId(circleId);
			circleMemberDao.delete(circleMember);// 删除全体圈子成员

			imGroupService.deleteGroup(circleId);// 删除IM群组
		}
	}

	@Override
	public List<CircleBaseVo> queryListByCircleIds(List<Integer> circleIds) {
		if (circleIds == null || circleIds.size() == 0) {
			return new ArrayList<CircleBaseVo>(0);
		}
		CircleBaseQuery circleBaseQuery = new CircleBaseQuery();
		circleBaseQuery.setCircleIds(circleIds);// 圈子ID列表
		circleBaseQuery.setStatus(CircleBaseStatusDictEnum.NORMAL.getCode());
		return circleBaseDao.queryList(circleBaseQuery);
	}

	/**
	 * 创建圈子前检查名称 根据圈子的类型进行不同规则检查
	 * 
	 * @param circleBase
	 * @throws BizzException
	 */
	private void checkCircleName(CircleBase circleBase) throws BizzException {
		if (circleBase.getType() == null) {
			throw new BizzException("圈子类型为空!");
		}
		if (circleBase.getType() == CircleBaseTypeDictEnum.OFFICIAL.getCode()) {
			// 官方圈子不能重名（全国唯一）
			CircleBase circle = new CircleBase();
			circle.setName(circleBase.getName());
			circle.setStatus(CircleBaseStatusDictEnum.NORMAL.getCode());
			circle.setType(CircleBaseTypeDictEnum.OFFICIAL.getCode());
			if (circleBaseDao.queryCount(circle) > 0) {
				throw new BizzException("该官方圈子名称已存在,不能重名!");
			}
		} else {
			if (circleBase.getCommunityId() != null) {
				// 社区圈子（同一社区内同一个人不能创建同名圈子）
				CircleBase circle = new CircleBase();
				circle.setCommunityId(circleBase.getCommunityId());// 社区id
				circle.setCreatorId(circleBase.getCreatorId());// 创建者id
				circle.setName(circleBase.getName());
				circle.setStatus(CircleBaseStatusDictEnum.NORMAL.getCode());
				if (circleBaseDao.queryCount(circle) > 0) {
					throw new BizzException("您已在本社区创建了一个同名圈子,请使用其他名称!");
				}
			}
			if (circleBase.getCreatorId() == null) {
				throw new BizzException("创建者id不能为空!");
			}

		}
	}

	@Override
	public int queryMyCreatedCircleCount(int userId) {
		CircleBase circle = new CircleBase();
		circle.setCreatorId(userId);// 圈主
		circle.setStatus(CircleBaseStatusDictEnum.NORMAL.getCode());
		return circleBaseDao.queryCount(circle);
	}

	@Override
	public void changeCircleFuncType(Integer circleId, CircleFuncTypeDictEnum funcTypeEnum) {
		CircleBase circle = new CircleBase();
		circle.setId(circleId);
		circle.setFuncType(funcTypeEnum.getCode());
		circleBaseDao.updateById(circle);
	}

	@Override
	public int addCircle4Chat(CircleBase circleBase, List<Integer> memberIds) throws BizzException {
		if (circleBase.getCreatorId() == null) {
			throw new BizzException("创建者id不能为空!");
		}
		if (memberIds.size() < 2) {
			throw new BizzException("成员人数不能小于2！");
		}
		if (circleBase.getCategoryName() == null) {
			circleBase.setCategoryName("");
		}
		circleBase.setType(CircleBaseTypeDictEnum.POPULAR.getCode());// 民间
		circleBase.setStatus(CircleBaseStatusDictEnum.NORMAL.getCode());
		circleBase.setFuncType(CircleFuncTypeDictEnum.CHATONLY.getCode());// 只可以聊天
		if (circleBase.getOpenLevel() == null) {
			circleBase.setOpenLevel(CircleOpenLevelDictEnum.FULL_OPEN.getCode());// 如果不设置,默认完全公开（用户可以自由加入）
		}
		int circleId = this.insert(circleBase);// 1.保存圈子主表信息
		CircleMember circleMember = null;
		circleMember = new CircleMember();
		circleMember.setCircleId(circleId);
		circleMember.setMemberId(circleBase.getCreatorId());
		circleMember.setType(CircleMemberTypeDictEnum.OWNER.getCode());
		circleMemberDao.insert(circleMember);// 2.保存圈子成员【圈主】
		for (Integer memberId : memberIds) {
			circleMember = new CircleMember();
			circleMember.setCircleId(circleId);
			circleMember.setMemberId(memberId);
			circleMember.setType(CircleMemberTypeDictEnum.MEMBER.getCode());
			circleMemberDao.insert(circleMember);// 3.保存圈子成员
		}

		CircleInfo circleInfo = new CircleInfo();
		circleInfo.setId(circleId);
		circleInfo.setMemberCount(memberIds.size());
		circleInfo.setTopicCount(0);
		circleInfo.setPv(0);
		circleInfoDao.insert(circleInfo);// 4.保存圈子扩展信息

		// 添加IM群组(附上成员id列表，不含群主id)
		imGroupService.addImGroupAndMember(circleId, circleBase.getName(), 1000, circleBase.getCreatorId(), memberIds);

		return circleId;
	}

	@Override
	public List<CircleBaseVo> queryMyManageCircles(int userId) {
		List<Integer> myManageCircleIds = circleMemberDao.queryMyManageCircleIds(userId);
		if (myManageCircleIds != null && myManageCircleIds.size() > 0) {
			return this.queryListByCircleIds(myManageCircleIds);
		} else {
			return Lists.newArrayList();
		}
	}

	@Override
	public void updateAllMemberCanAddVote(Integer circleId, YesNoEnum isCanAddVote) {
		CircleMember member4update = new CircleMember();
		member4update.setCircleId(circleId);
		member4update.setCanAddVote(isCanAddVote.getCode());
		circleMemberDao.updateByCircleId(member4update);
	}

	@Override
	public void updateAllMemberCanAddActivity(Integer circleId, YesNoEnum isCanAddActivity) {
		CircleMember member4update = new CircleMember();
		member4update.setCircleId(circleId);
		member4update.setCanAddActivity(isCanAddActivity.getCode());
		circleMemberDao.updateByCircleId(member4update);
	}

	@Override
	public boolean isKeepAllMemberNoVote(Integer circleId) {
		CircleMember member = new CircleMember();
		member.setCircleId(circleId);
		member.setCanAddVote(YesNoEnum.YES.getCode());
		// 如果存在一个人可以发投票，表示没有“禁止所有成员发投票”
		return !(circleMemberDao.queryCount(member) > 0);
	}

	@Override
	public boolean isKeepAllMemberNoActivity(Integer circleId) {
		CircleMember member = new CircleMember();
		member.setCircleId(circleId);
		member.setCanAddActivity(YesNoEnum.YES.getCode());
		// 如果存在两个人可以发活动，表示没有“禁止所有成员发活动”
		return !(circleMemberDao.queryCount(member) > 0);
	}

	@Override
	public int setRecommend(Integer circleId, Integer recommendOidx) throws BizzException {
		if (circleId == null || circleId == 0) {
			throw new BizzException("圈子id为空！");
		}

		if (recommendOidx == null || recommendOidx == 0) {
			throw new BizzException("排序位置为空！");
		}
		CircleBaseVo circleVo = circleBaseDao.getById(circleId);
		if (circleVo == null) {
			throw new BizzException("找不到这个圈子！");
		}
		if (circleVo.getIsOfficial()) {
			throw new BizzException("不能推荐官方圈子！");
		}

		CircleBase updateCircle = new CircleBase();
		updateCircle.setId(circleId);
		updateCircle.setIsRecommend(YesNoEnum.YES.getCode());
		updateCircle.setRecommendAt(TimeUtil.now());
		updateCircle.setRecommendOidx(recommendOidx);

		return circleBaseDao.updateById(updateCircle);
	}

	@Override
	public int setUnRecommend(Integer circleId) throws BizzException {
		if (circleId == null || circleId == 0) {
			throw new BizzException("圈子id为空！");
		}
		CircleBaseVo circleVo = circleBaseDao.getById(circleId);
		if (circleVo == null) {
			throw new BizzException("找不到这个圈子！");
		}
		CircleBase updateCircle = new CircleBase();
		updateCircle.setId(circleId);
		updateCircle.setIsRecommend(YesNoEnum.NO.getCode());
		updateCircle.setRecommendAt(TimeUtil.now());
		updateCircle.setRecommendOidx(99);
		return circleBaseDao.updateById(updateCircle);
	}

	@Override
	public List<CircleBaseVo> queryMyGroupChats(int userId) {
		List<Integer> myGroupChatIds = circleMemberDao.queryMyGroupChatIds(userId);
		if (myGroupChatIds != null && myGroupChatIds.size() > 0) {
			return this.queryListByCircleIds(myGroupChatIds);
		} else {
			return Lists.newArrayList();
		}
	}

	@Override
	public int showMemberGrade(int circleId) {
		CircleBase circle = new CircleBase();
		circle.setId(circleId);
		circle.setIsShowMemberGrade(YesNoEnum.YES.getCode());
		return circleBaseDao.updateById(circle);
	}

	@Override
	public int hideMemberGrade(int circleId) {
		CircleBase circle = new CircleBase();
		circle.setId(circleId);
		circle.setIsShowMemberGrade(YesNoEnum.NO.getCode());
		return circleBaseDao.updateById(circle);
	}

	@Override
	public int auditPass(Integer circleId) {
		CircleBase circle = new CircleBase();
		circle.setId(circleId);
		circle.setAuditStatus(CircleAuditStatusEnum.AUDIT_PASS.getCode());
		circle.setAuditAt(TimeUtil.now());
		return circleBaseDao.updateById(circle);
	}

	@Override
	public int undoAudit(Integer circleId) {
		CircleBase circle = new CircleBase();
		circle.setId(circleId);
		circle.setAuditStatus(CircleAuditStatusEnum.WAITING.getCode());
		circle.setAuditAt(TimeUtil.now());
		return circleBaseDao.updateById(circle);
	}

	@Override
	public int auditNotPass(Integer circleId) {
		CircleBase circle = new CircleBase();
		circle.setId(circleId);
		circle.setAuditStatus(CircleAuditStatusEnum.AUDIT_NOTPASS.getCode());
		circle.setAuditAt(TimeUtil.now());
		return circleBaseDao.updateById(circle);
	}

	@Override
	public LinkedHashMap<Integer, CircleBaseVo> getMyCirclesMap(Integer userId) {
		LinkedHashMap<Integer, CircleBaseVo> map = new LinkedHashMap<Integer, CircleBaseVo>();
		CircleMemberQuery query = new CircleMemberQuery();
		query.setMemberId(userId);
		List<CircleBaseVo> circleList = this.queryMyCircles(query);
		if (circleList != null && circleList.size() > 0) {
			for (CircleBaseVo circle : circleList) {
				if (null == map.get(circle.getId())) {
					map.put(circle.getId(), circle);
				}
			}
		}
		return map;
	}

	@Override
	public List<CircleBaseVo> getRecommendCircleList(Integer communityId, int returnCount) {
		CircleBaseQuery circleQuery = new CircleBaseQuery();
		List<Integer> includeFunctypeList = Lists.newArrayList();
		includeFunctypeList.add(CircleFuncTypeDictEnum.ALL.getCode());
		includeFunctypeList.add(CircleFuncTypeDictEnum.TOPICONLY.getCode());
		circleQuery.setIncludeFuncTypes(includeFunctypeList);// 去掉群聊
		if (communityId != null) {
			circleQuery.setCommunityId(communityId);
		}
		circleQuery.setAuditStatus(CircleAuditStatusEnum.AUDIT_PASS.getCode());// 审核通过的
		circleQuery.setStatus(CircleBaseStatusDictEnum.NORMAL.getCode());
		circleQuery.setIsRecommend(YesNoEnum.YES.getCode());

		Pageable pageKit = new PageKit(1, returnCount, new PageOrder(Direction.ASC, "recommendOidx"));// 最后推荐的放到最前面
		return circleBaseDao.queryList(circleQuery, pageKit);
	}

	@Override
	public List<CircleBaseVo> getCircleList4Community(Integer communityId) {
		CircleBaseQuery circleQuery = new CircleBaseQuery();
		circleQuery.setCommunityId(communityId);
		circleQuery.setAuditStatus(CircleAuditStatusEnum.AUDIT_PASS.getCode());// 审核通过的
		circleQuery.setStatus(CircleBaseStatusDictEnum.NORMAL.getCode());
		List<Integer> includeOpenLevelList = Lists.newArrayList();
		includeOpenLevelList.add(CircleOpenLevelDictEnum.FULL_OPEN.getCode());
		includeOpenLevelList.add(CircleOpenLevelDictEnum.HALF_OPEN.getCode());

		CommunityBase communityBase = communityBaseDao.getById(communityId);
		if (communityBase != null && communityBase.getCityId() != null && communityBase.getCityId().intValue() != 0) {
			circleQuery.setCityId(communityBase.getCityId());
		} else {
			circleQuery.setCityId(null);
		}

		Pageable pageKit = new PageKit(1, Integer.MAX_VALUE, new PageOrder(Direction.ASC, "recommendOidx"));
		return circleBaseDao.queryList(circleQuery, pageKit);
	}
}